﻿#ifndef __SWAPPINGLIST_H__
#define __SWAPPINGLIST_H__

#include "Common.h"
#include "Mutex.h"

using namespace sky;

/**
@name : 翻转队列
@brief: 在多线程生产者-消费者模式中生产者线程向队列添加对象，消费者线程从队列取走对象
        因为涉及到多线程访问，这个队列必须在添加/取走对象时加锁。这个模版实现这种多线程
		安全的队列，另外使用两个队列翻转的技术，可以极大的减少锁互斥的几率
*/

template<typename _OBJ>
class SwappingList
{

public:
    SwappingList()
    {
            m_frontList = new PRODUCT_LIST;
            m_backList = new PRODUCT_LIST;

            m_nCount = 0;
    }

    virtual ~SwappingList()
    {
        if (m_frontList)
        {
            delete m_frontList;
            m_frontList = 0;
        }

        if (m_backList)
        {
            delete m_backList;
            m_backList = 0;
        }
    }

public:
    size_t Add(_OBJ& obj)
    {
        ::InterlockedIncrement(&m_nCount);
        scopelock lock(m_frontMutex);

        m_frontList->push_back(obj);
        
        return m_frontList->size();
    }

    bool Get(_OBJ & obj)
    {
        if (m_nCount == 0)
        {
            return false;
        }

        static unsigned long s_last_trace = 0;
        if (m_nCount > 1000 && GetTickCount() - s_last_trace > 1000)
        {
            s_last_trace = GetTickCount();
            if (sizeof(_OBJ) == 4)
            {
                //todo
                // WarningLn("The queues that received packet blocking "<<m_nCount );
            }
            else
            {
                //todo
                // WarningLn("The queues that sent packet blocking "<<m_nCount );
            }
        }

        if (m_backList->empty())
        {
            Swap();
        }

        if (m_backList->empty())
        {
            return false;
        }

        ::InterlockedDecrement(&m_nCount);
        obj = m_backList->front();
        m_backList->pop_front();

        return true;
    }

    int Count()
    {
        return m_nCount;
    }

    void Swap()
    {
        scopelock lock(m_frontMutex);

        PRODUCT_LIST * p = m_backList;
        m_backList = m_frontList;
        m_backList = p;
    }
    
protected:
    typedef std::list<_OBJ>     PRODUCT_LIST;
    PRODUCT_LIST * m_frontList;
    PRODUCT_LIST * m_backList;

    Mutex   m_frontMutex;
    volatile long   m_nCount;
};

#endif